import datetime
import json
import logging
import time

from django.db.models import Sum
from rest_framework.generics import ListAPIView

from wine import settings
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt

from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from wechatpy import parse_message, WeChatOAuth
from wechatpy.exceptions import InvalidSignatureException
from wechatpy.replies import TransferCustomerServiceReply, ImageReply, VoiceReply, create_reply

from wechatpy.utils import check_signature, random_string
from wxchat.api.permissions import WeixinPermission
from wxchat.api.serializers import WxUserInfoSerializer, RechargeListSerializer, RechargeRecordSerializer
from wxchat.api.utils import wxClient
from wxchat.models import WxUserInfo, RechargeList, RechargeRecord

logger = logging.getLogger("django")


weChatOAuth = WeChatOAuth(settings.WECHAT_APPID, settings.WECHAT_SECRET, "", 'snsapi_userinfo')


def getJsApiSign(request):
    """
    微信JSAPI支付
    """
    url = request.GET.get("url", None)
    logging.info(url)
    client = wxClient()
    ticket = client.jsapi.get_jsapi_ticket()

    noncestr = random_string(15)
    timestamp = int(time.time())
    signature = client.jsapi.get_jsapi_signature(noncestr, ticket, timestamp, url)
    sign_package = {
        "appId": settings.WECHAT_APPID,
        "nonceStr": noncestr,
        "timestamp": timestamp,
        "signature": signature
    }
    logging.info(sign_package)
    return JsonResponse(sign_package)


@csrf_exempt
def wechat(request):
    if request.method == 'GET':
        signature = request.GET.get('signature', None)
        timestamp = request.GET.get('timestamp', None)
        nonce = request.GET.get('nonce', None)
        echostr = request.GET.get('echostr', None)

        try:
            check_signature(settings.WECHAT_TOKEN, signature, timestamp, nonce)
        except InvalidSignatureException:
            echostr = 'error'

        return HttpResponse(echostr)

    elif request.method == 'POST':
        msg = parse_message(request.body)
        print('+++++:', msg, msg.type)
        if msg.type == 'text':
            reply = TransferCustomerServiceReply(message=msg)
        elif msg.type == 'image':
            reply = ImageReply(message=msg)
            reply.media_id = msg.media_id
        elif msg.type == 'voice':
            reply = VoiceReply(message=msg)
            reply.media_id = msg.media_id
            reply.content = '语音信息'
        elif msg.type == 'event':
            print('eventkey=', msg.event)
            if msg.event == 'subscribe':
                saveUserinfo(msg.source)
                reply = create_reply('您好，惠生活礼品欢迎您！！', msg)
            elif msg.event == 'unsubscribe':
                reply = create_reply('取消关注公众号', msg)
                unSubUserinfo(msg.source)
            elif msg.event == 'subscribe_scan':
                reply = create_reply('您好，惠生活礼品欢迎您！！', msg)
                saveUserinfo(msg.source, msg.scene_id)
            elif msg.event == 'scan':
                reply = create_reply('', msg)
            else:
                reply = create_reply('view', msg)
        else:
            reply = create_reply('', msg)

        response = HttpResponse(reply.render(), content_type="application/xml")
        return response


def saveUserinfo(openid, scene_id=None):
    """
    保存或更新关注用户信息
    :param openid:
    :param scene_id:
    :return:
    """
    client = wxClient()
    user = client.user.get(openid)
    if 'errcode' not in user:
        user.pop('groupid')
        user.pop('qr_scene_str')
        user.pop('remark')
        user.pop('tagid_list')
        sub_time = user.pop('subscribe_time')
        sub_time = datetime.datetime.fromtimestamp(sub_time)
        user['subscribe_time'] = sub_time
        obj, created = WxUserInfo.objects.update_or_create(defaults=user, openid=openid)
        logger.info(obj)
        logger.info(created)
    else:
        logger.info(user)


def unSubUserinfo(openid):
    """
    取消订阅
    :param openid:
    :return:
    """
    try:
        user = WxUserInfo.objects.get(openid=openid)
        user.subscribe = 0
        user.save()
    except WxUserInfo.DoesNotExist as ex:
        logging.info(ex)


# class WxMenuAPIView(APIView):
#     authentication_classes = ()
#     permission_classes = ()
#
#     def get(self, request, *args, **kwargs):
#         res = self.get_menu()
#         return Response(res)
#
#     def post(self, request, *args, **kwargs):
#         flag = request.data.get("flag", None)
#         print(flag)
#         res = None
#         if flag == "create":
#             res = self.create_menu()
#         elif flag == "delete":
#             res = self.delete_menu()
#         print(res)
#         return Response(res)
#
#     def create_menu(self):
#         client = wxClient()
#         resp = client.menu.create({
#             "button": [
#                 {
#                     "type": "view",
#                     "name": "附近电桩",
#                     "url": settings.ROOT_URL + "/#station"
#                 },
#                 {
#                     "type": "view",
#                     "name": "充电桩",
#                     "url": settings.ROOT_URL + "/#pile"
#                 },
#                 # {
#                 #     "type": "view",
#                 #     "name": "扫码充电",
#                 #     "url": settings.ROOT_URL + "/wechat/scanqrcode/"
#                 # },
#                 {
#                     "type": "view",
#                     "name": "个人中心",
#                     "url": settings.ROOT_URL + "/#person"
#                 },
#
#             ]
#         })
#         return resp
#
#     def delete_menu(self):
#         client = wxClient()
#         resp = client.menu.delete()
#         return resp
#
#     def get_menu(self):
#         client = wxClient()
#         resp = client.menu.get()
#         return resp
#

def getWeChatAuthCode(request):
    code = request.GET.get('code', None)
    if code is None:  # 获取授权码code
        url = request.GET.get('url', None)
        redirect_url = url or settings.WEB_URL
        weChatOAuth.redirect_uri = redirect_url

        authorize_url = weChatOAuth.authorize_url

        res = {
            'status_code': 200,
            "authorize_url": authorize_url
        }
        return JsonResponse(res)


def getWeChatAuth(request):
    code = request.GET.get('code', None)
    res = weChatOAuth.fetch_access_token(code)
    if 'errcode' in res:
        return HttpResponse(json.dumps(res))
    else:
        open_id = weChatOAuth.open_id
        userinfo = weChatOAuth.get_user_info()
        userinfo.pop('privilege')
        obj, created = WxUserInfo.objects.update_or_create(openid=open_id, defaults=userinfo)

        data = {
            'status_code': 200,
            'openid': open_id,
        }
        return JsonResponse(data)


# 获取用户openid列表
def get_user_info(request):
    client = wxClient()
    userid_list = client.user.get_followers()
    logger.info(userid_list)
    WxUserInfo.objects.all().update(qr_scene=0)

    if 'errcode' not in userid_list and userid_list['count'] > 0:
        openid_list = userid_list['data']['openid']
        n = 100
        for openids in [openid_list[i:i + n] for i in range(0, len(openid_list), n)]:
            print("openids:", openids)
            userinfo_lists = client.user.get_batch(openids)
            for user in userinfo_lists:
                logger.info(user)
                sub_time = user.pop('subscribe_time')
                sub_time = datetime.datetime.fromtimestamp(sub_time).strftime('%Y-%m-%d %H:%M:%S')
                user['subscribe_time'] = sub_time
                WxUserInfo.objects.update_or_create(defaults=user, openid=user['openid'])

    return HttpResponse(json.dumps(userid_list, ensure_ascii=False))


class WeChatUserViewSet(ModelViewSet):
    """充电用户信息(公众号号)"""
    authentication_classes = ()
    permission_classes = (WeixinPermission,)
    queryset = WxUserInfo.objects.all()
    serializer_class = WxUserInfoSerializer
    lookup_field = 'openid'
    lookup_url_kwarg = 'openid'


class WxRechargeViewSet(ReadOnlyModelViewSet):
    """充值列表"""
    authentication_classes = ()
    permission_classes = (WeixinPermission,)
    pagination_class = None
    queryset = RechargeList.objects.all()
    serializer_class = RechargeListSerializer


class WxRechargeRecordViewSet(ReadOnlyModelViewSet):
    """用户充值记录表"""
    authentication_classes = ()
    permission_classes = (WeixinPermission,)
    queryset = RechargeRecord.objects.all()
    serializer_class = RechargeRecordSerializer

    def get_queryset(self):
        queryset = super().get_queryset()
        retailer_id = self.request.query_params.get("retailer_id", None)
        begin_date = self.request.query_params.get("begin_date", None)
        end_date = self.request.query_params.get("end_date", None)

        if retailer_id:
            queryset = queryset.filter(retailer_id=int(retailer_id))

        if begin_date and end_date:
            queryset = queryset.filter(pay_time__date__range=[begin_date, end_date])

        queryset = queryset.filter(status=1)

        return queryset


class WxRechargeStatsAPIView(APIView):
    """商家充值统计"""
    authentication_classes = ()
    permission_classes = (WeixinPermission,)

    def get(self, request, *args, **kwargs):
        retailer_id = request.query_params.get("retailer_id", None)
        begin_date = request.query_params.get("begin_date", None)
        end_date = request.query_params.get("end_date", None)

        queryset = RechargeRecord.objects.filter(status=1)
        if retailer_id:
            queryset = queryset.filter(retailer_id=retailer_id)

        if begin_date and end_date:
            queryset = queryset.filter(update_time__date__range=[begin_date, end_date])

        results = queryset.aggregate(cash_fees=Sum('cash_fee'), scores=Sum('score'))

        return Response(results)
